package main

import (
	"context"
	"fmt"
	"time"
)

func simple() {
	// 创建一个根Context
	rootContext := context.Background()

	// 创建一个带有超时时间的Context，这里设置超时时间为2秒
	ctx, cancel := context.WithTimeout(rootContext, 2*time.Second)
	defer cancel()

	// 在新的goroutine中执行任务
	go func(ctx context.Context) {
		select {
		case <-time.After(2 * time.Second):
			fmt.Println("任务完成")
		case <-ctx.Done():
			fmt.Println("任务取消或超时")
		}
	}(ctx)

	// 等待一段时间，模拟程序运行
	time.Sleep(5 * time.Second)
}

// ----------------------------------------------------------------------------------------------

type key string

func WithValue() {
	// 创建一个根Context
	rootContext := context.Background()

	// 使用WithValue传递数据
	ctx := context.WithValue(rootContext, key("userID"), 123)

	// 在子函数中获取传递的数据
	getUserID(ctx)
}

func getUserID(ctx context.Context) {
	// 从Context中获取数据
	if userID, ok := ctx.Value(key("userID")).(int); ok {
		fmt.Println("UserID:", userID)
	} else {
		fmt.Println("UserID不存在")
	}
}

// ----------------------------------------------------------------------------------------------
func cancelOrTimeout() {
	// 创建一个根Context
	rootContext := context.Background()

	// 创建一个超时时间为2秒的Context
	timeoutCtx, _ := context.WithTimeout(rootContext, 2*time.Second)

	// 创建一个手动取消的Context
	cancelCtx, cancel := context.WithCancel(rootContext)
	defer cancel()

	// 在新的goroutine中执行任务
	go func(ctx context.Context) {
		select {
		case <-time.After(3 * time.Second):
			fmt.Println("任务完成")
		case <-ctx.Done():
			fmt.Println("任务取消或超时")
		}
	}(timeoutCtx)

	// 在另一个goroutine中执行任务
	go func(ctx context.Context) {
		select {
		case <-time.After(1 * time.Second):
			fmt.Println("另一个任务完成")
		case <-ctx.Done():
			fmt.Println("另一个任务取消")
		}
	}(cancelCtx)

	// 等待一段时间，模拟程序运行
	time.Sleep(5 * time.Second)
}

// ----------------------------------------------------------------------------------------------
func cancleCtx() {
	// 创建一个根Context
	rootContext := context.Background()

	// 创建一个可以手动取消的Context
	ctx, cancel := context.WithCancel(rootContext)
	defer cancel()

	// 在新的goroutine中执行任务
	go func(ctx context.Context) {
		select {
		case <-time.After(3 * time.Second):
			fmt.Println("任务完成")
		case <-ctx.Done():
			fmt.Println("任务取消")
		}
	}(ctx)

	// 等待一段时间，手动取消任务
	time.Sleep(2 * time.Second)
	cancel()

	// 等待一段时间，模拟程序运行
	time.Sleep(1 * time.Second)
}

// ----------------------------------------------------------------------------------------------
func cancleOrTimeout2() {
	// 创建一个带有超时的context
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)

	go func() {
		time.Sleep(7 * time.Second)
		cancel()
	}()

	// 模拟一个任务，它会检查context的完成原因
	go doTask(ctx)

	// 检查context是否已经完成
	select {
	case <-ctx.Done():
		// 根据错误判断完成原因
		switch ctx.Err() {
		case context.Canceled:
			fmt.Println("Context was cancelled")
			return
		case context.DeadlineExceeded:
			fmt.Println("Context has timed out")
			return
		}

	}
}

func doTask(ctx context.Context) {
	// 模拟其他任务执行
	time.Sleep(10 * time.Second)

}

// ----------------------------------------------------------------------------------------------

func main() {

	//simple()
	//WithValue()
	//cancelOrTimeout()
	//cancleCtx()
	cancleOrTimeout2()
}
